<template>
  <div
      style="position: fixed;top:0;left:0;width:100vw;height:100vh; -webkit-mask-image: radial-gradient(circle, transparent, black);--webkit-mask-image: radial-gradient(circle, transparent, black);">
    <canvas ref="el" :width="WIDTH" :height="HEIGHT"></canvas>
  </div>
</template>
<script setup lang="ts">
import {onMounted, ref, computed} from "vue";
import {useRafFn} from '@vueuse/core'

const {random} = Math

const el = ref<HTMLCanvasElement>()
const ctx = computed(() => {
  return el.value?.getContext('2d')
})
let WIDTH = 0
let HEIGHT = 0

const stopped = ref(false)

interface Point {
  x: number
  y: number
}

interface Branch {
  start: Point
  length: number
  theta: number
}

const len = ref(10)
let steps: () => void[] = []
let prevSteps: () => void[] = []
let iterations = 0

function step(b: Branch) {
  const length = random() * len.value

  const end = getEndPoint(b)
  lineTo(b.start, getEndPoint(b))

  if (end.x < -100 || end.x > WIDTH || end.y < -100 || end.y > HEIGHT || iterations > 200)
    return
  if (iterations < 5 || Math.random() < 0.48) {
    steps.push(
        () => step({
          start: end,
          length: length,
          theta: b.theta - 0.3
        })
    )
  }
  if (iterations < 5 || Math.random() < 0.48) {
    steps.push(() => step({
          start: end,
          length: length,
          theta: b.theta + 0.3
        })
    )
  }
}

function frame() {
  iterations += 1
  prevSteps = [...steps]
  steps.length = 0

  if (!prevSteps.length) {
    controls.pause()
    stopped.value = true
  }
  prevSteps.forEach(fn => fn())
}

const controls = useRafFn(frame, {immediate: false})

function start() {
  el.value.width = WIDTH * window.devicePixelRatio
  el.value.height = HEIGHT * window.devicePixelRatio
  ctx.value.clearRect(0, 0, WIDTH, HEIGHT)
  // 线条设置
  ctx.value.lineWidth = 0.2
  ctx.value.strokeStyle = '#767474'

  // 第一个分支
  const branch = {
    start: {x: WIDTH * 0.2, y: HEIGHT},
    length: 10,
    theta: -Math.PI / 2,
  }
  step(branch)

  // 第一个分支
  const branchTwo = {
    start: {x: WIDTH * 0.8, y: HEIGHT},
    length: 10,
    theta: -Math.PI / 2,
  }
  step(branchTwo)

  controls.pause()
  iterations = 0
  prevSteps = []
  controls.resume()
  stopped.value = false
}

function lineTo(p1: Point, p2: Point) {
  ctx.value.beginPath()
  ctx.value.moveTo(p1.x, p1.y)
  ctx.value.lineTo(p2.x, p2.y)
  ctx.value.stroke()
}

function getEndPoint(b: Branch) {
  return {
    x: b.start.x + b.length * Math.cos(b.theta),
    y: b.start.y + b.length * Math.sin(b.theta)
  }
}


onMounted(() => {
  WIDTH = window.innerWidth
  HEIGHT = window.innerHeight
  start()
})

</script>



